﻿using Volo.Abp.Modularity;
using Volo.Abp;
using Volo.Abp.AspNetCore.Mvc;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Hosting;
using WorkFlowCore.Common.EventBus;
using Microsoft.Extensions.DependencyInjection;
using WorkFlowCore.Framework;
using WorkFlowCore.Host.Controllers.Filters;
using Microsoft.OpenApi.Models;
using System.Reflection;
using System;
using System.IO;
using Volo.Abp.AspNetCore.Mvc.AntiForgery;
using Volo.Abp.EventBus;
using Volo.Abp.BackgroundWorkers.Quartz;
using WorkFlowCore.Host.Filters;
using WorkFlowCore.Common.Authentication.JWT;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using System.Configuration;
using IdentityModel;
using System.Security.Claims;
using WorkFlowCore.Common.Authorization.JWT;
using System.Linq;
using Autofac.Core;

namespace WorkFlowCore.Host
{

    [DependsOn(typeof(WorkFlowCoreFrameworkModule))]
    [DependsOn(typeof(AbpEventBusModule))]
    [DependsOn(typeof(AbpAspNetCoreMvcModule))]
    [DependsOn(typeof(AbpBackgroundWorkersQuartzModule) //Add the new module dependency
    )]
    public class AppModule : AbpModule
    {
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            base.ConfigureServices(context);
            var services = context.Services;

            services.AddControllersWithViews(options =>
            {
                options.Filters.Add<ExceptionFilter>();
                options.Filters.Add<ResultFilter>();
            });

            services.AddAuthentication(options =>
            {
                options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;

                services.AddAuthorization(options =>
                {
                    options.AddPolicy("DefaultPolicy", policy =>
                    {
                        policy.RequireClaim(JwtClaimTypes.Issuer, JWTAuthenticationOptions.JwtClaimTypesIssuer);
                        policy.RequireClaim(JwtClaimTypes.Audience, JWTAuthenticationOptions.JwtClaimTypesAudience);
                    });
                });
            })
           .AddCommonJwtBearer(options =>
           {
               options.SecretKey = services.GetConfiguration()["Authentication:JwtBearer:SecretKey"];
           });


            //注册swagger
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1.0", new OpenApiInfo { Title = "流程服务", Version = "1.0" });
                var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
                var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
                c.IncludeXmlComments(xmlPath);
                c.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "WorkFlowCore.xml"));

                c.OperationFilter<AuthenticationAuthTokenHeaderParameter>();

                {
                    var securityScheme = new OpenApiSecurityScheme()
                    {
                        Description = "asscess token",
                        Name = "Authorization",
                        In = ParameterLocation.Header,
                        Type = SecuritySchemeType.Http,
                        Scheme = "Bearer",
                        BearerFormat = "JWT"

                    };
                    var securityRequirement = new OpenApiSecurityRequirement()
                    {
                        {
                            new OpenApiSecurityScheme
                            {
                                Reference = new OpenApiReference
                                {
                                    Type = ReferenceType.SecurityScheme,
                                    Id="bearerAuth"
                                }
                            },
                            new string[]{ }
                        }
                    };

                    c.AddSecurityDefinition("bearerAuth", securityScheme);
                    c.AddSecurityRequirement(securityRequirement);
                }
            });

            // Configure CORS for angular2 UI
            var allowedHosts = context.Services.GetConfiguration()["AllowedHosts"];
            services.AddCors(
                options => options.AddPolicy(
                    "defaultcors",
                    builder =>
                    {
                        if (allowedHosts == "*")
                        {
                            builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod();
                        }
                        else
                        {
                            //App: CorsOrigins in appsettings.json can contain more than one address separated by comma.

                            builder.WithOrigins(
                                allowedHosts.Split(",", StringSplitOptions.RemoveEmptyEntries)
                               .ToArray()
                               //"http://localhost:9528".Split(',')
                               ).AllowAnyHeader()
                               .AllowAnyMethod()
                               .AllowCredentials();
                        }
                    }
                )
            );


            //加这个是避免请求提示认证
            Configure<AbpAntiForgeryOptions>(options =>
            {
                options.TokenCookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Lax;
                options.TokenCookie.Expiration = TimeSpan.FromDays(365);
                options.AutoValidateIgnoredHttpMethods.Add("POST");
                options.AutoValidateIgnoredHttpMethods.Add("PUT");
                options.AutoValidateIgnoredHttpMethods.Add("DELETE");
                options.AutoValidateIgnoredHttpMethods.Add("GET");
            });

            Configure<AbpBackgroundWorkerQuartzOptions>(options =>
            {
                options.IsAutoRegisterEnabled = true;
            });

            services.AddMemoryCache();
        }
        public override void OnApplicationInitialization(ApplicationInitializationContext context)
        {
            var app = context.GetApplicationBuilder();
            var env = context.GetEnvironment();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }
            app.UseCors("defaultcors");
            //app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseAuthorizationJWTHandler();

            app.UseAuthentication();
            app.UseRouting();



            app.UseAuthorization();

            if (env.IsDevelopment())
            {
                app.UseSwagger();
                app.UseSwaggerUI(c =>
                {
                    c.SwaggerEndpoint("/swagger/v1.0/swagger.json", "流程服务(V 1.0)");
                    //c.RoutePrefix = string.Empty;
                    //c.DocExpansion(Swashbuckle.AspNetCore.SwaggerUI.DocExpansion.None);// 默认折叠
                });

            }
            app.UseUnitOfWork();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}")
                .RequireAuthorization("DefaultPolicy");
                endpoints.MapControllerRoute(
                    name: "api",
                    pattern: "api/{controller=Home}/{action=Index}/{id?}")
                .RequireAuthorization("DefaultPolicy");

            });

            //注册全局事件总线
            //app.InitGlobalEventBus();

        }
    }
}
